#include "ObjFile.h"

using std::vector;
using namespace ObjData;

ObjPrimitive::ObjPrimitive() {
	Vertices = NULL;
	Indices = NULL;
}

void ObjPrimitive::Clear() {
	if(Vertices == NULL)
		return;

	delete [NumVertices] Vertices;
	Vertices = NULL;

	if(NumVertices >= 0x0000FFFF)
		delete [NumFaces * 3] Indicesl;
	else
		delete [NumFaces * 3] Indices;

	Indices = NULL;

	NumFaces = 0;
	NumVertices = 0;
}

void ObjPrimitive::SetParams(
	std::vector<Vector3> *Pos,
	std::vector<Vector2> *Tex,
	std::vector<Vector3> *Norm) {

	m_Pos = Pos;
	m_Tex = Tex;
	m_Norm = Norm;
}

int ObjPrimitive::GetVertexIndex(ObjData::Point *p) {
	for(unsigned int i = 0; i < m_Points.size(); i++)
		if(m_Points[i] == p)
			return i;

	return 0;
}

Vertex ObjPrimitive::BuildVertex(ObjData::Point *p) {
	Vertex v;

	/* If vertices have no reference to certain coordinates, fill in a blank default value instead
	
	In this case, I've elected for a normal pointing along an arbitrary axis (to avoid division by
	0 when it's normalized in the shaders), and 0,0 for the UV coordinates. The position is mandatory,
	however. I don't know whether this is the case in the file format definition, but I can't see a
	mesh being useful at all without it.*/

	v.Pos = m_Pos->at(p->Position - 1);

	if(p->Normal == 0)
		v.Normal = Vector3(0.0f, 0.0f, 1.0f);
	else
		v.Normal = m_Norm->at(p->Normal - 1);

	if(p->Texture == 0)
		v.UV = Vector2();
	else
		v.UV = m_Tex->at(p->Texture - 1);

	return v;
}

void ObjPrimitive::BuildObject(ObjData::Object *Obj) {
	Clear();

	int NumVerts = 0;
	int NumTris = 0;

	for each(Face f in Obj->Faces) {
		NumVerts += f.Points.size();
		NumTris += f.Points.size() - 2;
	}

	Vertices = new Vertex[NumVerts];
	int a = 0;
	
	m_Points.clear();
	// Build vertex list
	for each(Face f in Obj->Faces) {
		for each(Point p in f.Points) {
			Vertices[a] = this->BuildVertex(&p);

			m_Points.push_back(&p);
			a++;
		}
	}

	NumVertices = NumVerts;
	NumFaces = NumTris;

	if(NumVerts >= 0x0000FFFF)
		this->BuildIndices<unsigned long>(Obj);
	else
		this->BuildIndices<unsigned short>(Obj);
}

template<typename Ind>
void ObjPrimitive::BuildIndices(ObjData::Object *Obj) {
	Ind* MyInds = (Ind*)Indices;
	MyInds = new Ind[NumFaces * 3];
	IndexSize = sizeof(Ind);

	int a = 0;

	for each(Face f in Obj->Faces) {
		for(unsigned int i = 2; i < f.Points.size(); i++) {
			MyInds[a] = GetVertexIndex(&f.Points[0]);
			MyInds[a+1] = GetVertexIndex(&f.Points[1]);
			MyInds[a+2] = GetVertexIndex(&f.Points[i]);
			a+=3;
		}
	}
}

void ObjPrimitive::Build() {

}